package models

import (
	"GoAdmin/utils"
	"GoAdmin/utils/logs"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/spf13/cast"
	"go.uber.org/zap"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strings"
	"time"
	"xorm.io/builder"
)

type Coach struct {
	Id               int       `xorm:"not null pk autoincr comment('自增主键') INT(11)"`
	UserId           int       `xorm:"not null comment('用户id外键关联dts_user中的id') index INT(11)"`
	SchoolId         int       `xorm:"not null comment('驾校id外键关联dts_school中的自增id') index INT(11)"`
	IcId             int       `xorm:"default 0 comment('IC卡id,学员可以没有IC卡也可以拥有多张IC卡，当前为生效IC卡id') INT(11)"`
	InstitutionCode  string    `xorm:"comment('运管统一编号') index VARCHAR(16)"`
	FingerId         int       `xorm:"default 0 comment('指纹id，教练员可以拥有多个指纹记录，当前为生效指纹id') INT(11)"`
	PortraitId       int       `xorm:"default 0 comment('头像id，教练员可以拥有多个头像记录，当前为生效头像id') INT(11)"`
	LicenceNumber    string    `form:"licence_number" xorm:"default '' comment('驾驶证号') VARCHAR(128)"`
	LicenceGrantDate time.Time `xorm:"comment('驾驶证初领日期 YYYYMMDD') DATE"`
	OccupationNumber string    `form:"occupation_number" xorm:"default '' comment('教练员职业资格证件号') VARCHAR(128)"`
	OccupationRank   string    `form:"occupation_rank" xorm:"default '1' comment('教练员职业资格等级，1：一级，2：二级，3：三级，4：四级') ENUM('1','2','3','4')"`
	DrivingCarType   string    `form:"driving_car_type"  xorm:"default 'C1' comment('准驾车型') ENUM('A1','A2','A3','B1','B2','C1','C2','C3','C4','C5','D','E','F','M','N','P')"`
	DrivingCarTypes  string    `form:"driving_car_types"  xorm:"default 'C1' comment('准驾车型')"`
	TeachingCarType  string    `form:"teaching_car_type" xorm:"default 'C1' comment('准教车型') ENUM('A1','A2','A3','B1','B2','C1','C2','C3','C4','C5','D','E','F','M','N','P')"`
	TeachingCarTypes string    `form:"teaching_car_types" xorm:"default 'C1' comment('准教车型')"`
	EntryDate        time.Time `xorm:"comment('入职日期 YYYYMMDD') DATE"`
	DepartureDate    time.Time `xorm:"comment('离职日期 YYYYMMDD') DATE"`
	Status           string    `form:"status" xorm:"default '1' comment('0：在职, 1：离职') ENUM('0','1')"`
	ApprovalStatus   string    `xorm:"default '0' comment('教练员提交运管审核状态，0:待审核，1:通过审核，2:未通过审核') ENUM('0','1','2')"`
	RecordStatus     string    `xorm:"not null default '0' comment('备案状态 0:未备案 1:已备案') ENUM('0','1')"`
	RecordStatus2    string    `xorm:"not null default '0' comment('濮阳备案状态 0:未备案 1:已备案') ENUM('0','1')"`
	LoginStatus      string    `xorm:"default '0' comment('0：登出状态    1：登录状态') ENUM('0','1')"`
	CourseId         int       `xorm:"comment('班级id') index INT(11)"`
	FieldId          int64     `xorm:"comment('所属训练场') index INT(11)"`
	Starlevel        int       `xorm:"default 0 comment('1-10:1星级，10-20：2星级，:20-30；3星级，依次类推') index index(startlevel) INT(11)"`
	Servicetimes     int       `xorm:"default 0 comment('教练的服务次数') index(startlevel) INT(11)"`
	Subject          string    `form:"subject" xorm:"comment('1-科一，2-科二,3-科三，4科四') ENUM('1','2','3','4')"`
	CharstandardId   int64     `form:"charstandard_id" xorm:"default 0 comment('缴费班级ID') INT(11)"`
	Jsznumber        string    `xorm:"comment('档案编号') VARCHAR(255)"`
	Remark           string    `xorm:"comment('备注') VARCHAR(255)"`
	Isused           string    `xorm:"default '1' comment('0已删除 1在使用') ENUM('0','1')"`
	Clicknum         int       `xorm:"INT(11)"`
	AddTime          time.Time `xorm:"INT(11)"`
}

type CoachInformation struct {
	Id              int    `json:"id"`
	Name            string `json:"name"`
	Sex             string `json:"sex"`
	Phone           string `json:"phone"`
	IdNumber        string `json:"id_number"`
	Subject         string `json:"subject"`
	DrivingCarTypes string `json:"driving_car_types"`
	LoginStatus     string `json:"login_status"`
	TeachingCarType string `json:"teaching_car_type"`
	RecordStatus    string `json:"record_status"`
	SchoolName      string `json:"school_name"`
	ApprovalStatus  string `json:"approval_status"`
}

func (c *Coach) GetCoachByFilter(filter builder.Cond, pagesize, offset int) (count int64, list []*CoachInformation, err error) {
	err = engine.Table("dts_coach").Alias("ch").
		Select("ch.id,u.name,u.phone,u.sex,u.id_number,sl.name_short as school_name,ch.driving_car_types,ch.teaching_car_type,ch.approval_status,ch.record_status,ch.login_status,ch.subject").
		Join("left", []string{"dts_user", "u"}, "u.id = ch.user_id").
		Join("left", []string{"dts_school", "sl"}, "sl.id = ch.school_id").
		And(filter).Limit(pagesize, offset).Desc("ch.id").Find(&list)
	count, err = engine.Table("dts_coach").Alias("ch").
		Join("left", []string{"dts_user", "u"}, "u.id = ch.user_id").
		Join("left", []string{"dts_school", "sl"}, "sl.id = ch.school_id").
		And(filter).Count()
	return
}

type CoachDetailInfo struct {
	Name             string `json:"name"`
	Sex              string `json:"sex"`
	Address          string `json:"address"`
	IdNumber         string `json:"id_number"`
	Phone            string `json:"phone"`
	Isused           string `json:"isused"`
	LicenceNumber    string `json:"licence_number"`
	LicenceGrantDate string `json:"licence_grant_date"`
	TeachingCarType  string `json:"teaching_car_type"`
	EntryDate        string `json:"entry_date"`
	DrivingCarType   string `json:"driving_car_type"`
	TrainingCarType  string `json:"training_car_type"`
	InstitutionCode  string `json:"institution_code"`
	ApprovalStatus   string `json:"approval_status"`
	RecordStatus     string `json:"record_status"`
	HeadUrl          string `json:"head_url"`
	Subject          string `json:"subject"`
}

func (c *Coach) GetCoachDetailInfo(studentId string) (has bool, list CoachDetailInfo, err error) {
	has, err = engine.Table("dts_coach").Alias("ch").
		Select("u.name,u.phone,u.sex,u.id_number,u.address,u.nation,u.nationality,u.password,p.image_url as head_url,ch.isused,ch.driving_car_type,ch.licence_number,ch.licence_grant_date,ch.teaching_car_type,ch.entry_date,ch.subject,ch.record_status,ch.institution_code,ch.approval_status").
		Join("left", []string{"dts_user", "u"}, "u.id = ch.user_id").
		Join("left", []string{"dts_portrait", "p"}, "p.id = ch.portrait_id").
		Where("ch.id = ?", studentId).Get(&list)
	//log.Println(list, err)
	return
}

func (c *Coach) Logout(id string) bool {
	_, err := engine.Exec("update dts_coach set login_status = ? where id = ?", "0", id)
	return err == nil
}

type CoachDeleteInfo struct {
	Id              int    `json:"id" form:"id"`
	InstitutionCode string `json:"institution_code" form:"institution_code"`
	UserId          int    `json:"user_id" form:"user_id"`
	Province        string `json:"province" form:"province"`
	City            string `json:"city" form:"city"`
	LoginStatus     string `json:"login_status" form:"login_status"`
	RecordStatus    string `json:"record_status" form:"record_status"`
	Isused          string `json:"isused" form:"isused"`
	SchoolId        int    `json:"school_id" form:"school_id"`
}

func (c *Coach) GetDeleteCoachInfo(id string) (has bool, list CoachDeleteInfo, err error) {
	has, err = engine.Table("dts_coach").Alias("ch").
		Select("ch.id,ch.school_id,ch.institution_code,sl.user_id,sl.province,sl.city,ch.login_status,ch.record_status,ch.isused").
		Join("left", []string{"dts_school", "sl"}, "sl.id = ch.school_id").
		Where("ch.id = ?", id).Get(&list)
	return
}

type CoachUser struct {
	InstitutionCode string
	IdNumber        string
	Name            string
	Phone           string
	TeachingCarType string
	NameShort       string
}

// GetCoachByID 通过教练的id获取教练信息
func (c *Coach) GetCoachByID(id string) (coach Coach, err error) {
	_, err = engine.Table("dts_coach").Where("id = ?", id).Get(&coach)
	return coach, nil
}

type CoachInfo struct {
	Id         int    `json:"id"`
	SchoolCode string `json:"school_code"`
	Name       string `json:"name"`
	Sex        string `json:"sex"`
	Phone      string `json:"phone"`
	Address    string `json:"address"`
	IdNumber   string `json:"id_number"`
	Province   string `json:"province"`
	City       string `json:"city"`
	ImageUrl   string `json:"image_url"`
	PhotoCode  string `json:"photo_code"`
}

func (c *Coach) GetCoachInfo(id string) (coach CoachInfo, err error) {
	_, err = engine.Table("dts_coach").Alias("c").
		Select("c.id ,s.institution_code as school_code,user.address,user.sex,user.phone,user.id_number,user.name,s.province,s.city,p.image_url,p.institution_code as photo_code").
		Join("LEFT", []string{"dts_school", "s"}, "c.school_id=s.id").
		Join("LEFT", []string{"dts_user", "user"}, "c.user_id=user.id").
		Join("LEFT", []string{"dts_portrait", "p"}, "c.portrait_id = p.id").
		Where("c.id = ?", id).Get(&coach)
	return coach, err
}

// GetCoachByCarID 通过教练的id获取教练信息
func (c *Coach) GetCoachByCarID(car int) (coach *CoachUser, err error) {
	coach = new(CoachUser)
	if has, err := engine.Table("dts_coach").Alias("c").
		Select("c.institution_code,user.phone,user.id_number,user.name,c.teaching_car_type,s.name_short").
		Join("LEFT", []string{"dts_school", "s"}, "c.school_id=s.id").
		Join("LEFT", []string{"dts_user", "user"}, "c.user_id=user.id").
		Where("c.id=(select coach_id from dts_wait_brush_car where car_id=?)", car).Get(coach); err != nil || !has {
		return nil, err
	}
	return coach, nil
}

func (c *Coach) DelById(id int) bool {
	var (
		err error
	)
	c.Remark = c.InstitutionCode
	c.InstitutionCode = ""
	c.Isused = "0"
	c.Status = "0"
	_, err = engine.Table("dts_coach").Id(id).Cols("isused", "remark", "status", "institution_code").Update(c)
	if err != nil {
		log.Println(err)
		return false
	}
	return true
}

// GetTheoryCoachBySchoolID get theory coach by school_id
func GetTheoryCoachBySchoolID(school int, car, learnType string) (list Coach, err error) {
	//var (
	//	TrainCoachCarType = map[string][]string{
	//		"C1": {"C1", "A1", "A2"},
	//		"C2": {"C1", "A1", "A2", "C2"},
	//	}
	//)
	cars := utils.TeacherTrainCarTypeNew[car]
	//err = engine.Table("dts_coach").Where("school_id= ? and isused = ?", school, "1").In("teaching_car_type", TrainCoachCarType[car]).Find(&list)

	if learnType == "2" || learnType == "3" {
		if _, err := engine.Table("dts_coach").Select("id").Where("school_id=? and subject=? and approval_status=? and record_status=?", school, "1", "1", "1").In("teaching_car_type", cars).Limit(1).Get(&list); err != nil {
			return list, err
		}
	} else {
		if _, err := engine.Table("dts_coach").Select("id").Where("school_id=?", school).Limit(1).Get(&list); err != nil {
			return list, err
		}
	}

	return list, err
}

func (c *Coach) BaiduCheck(imgurl string, user *User, schooid string) (err error) {
	var (
		faceurl      string
		request      *http.Request
		response     *http.Response
		ret_maps     map[string]interface{}
		ret_maplog   map[string]interface{}
		databyte     []byte
		access_token string
	)

	faceurl = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=dVK2KtDUCCHU8zdWO4mA0xSf&client_secret=3W1jIetONrtSGjISdTZQrnEtyLkjNZs7"

	if request, err = http.NewRequest("POST", faceurl, nil); err != nil {
		return err
	}

	request.Header.Set("Content-Type", "application/json; charset=UTF-8")
	if response, err = http.DefaultClient.Do(request); err != nil {
		return err
	}

	defer response.Body.Close()
	databyte, err = ioutil.ReadAll(response.Body)
	if err != nil {
		return err
	}
	err = json.Unmarshal(databyte, &ret_maps)
	if err != nil {
		return err
	}
	access_token = ret_maps["access_token"].(string)

	//上传百度人脸库
	var faceaddurl string

	faceaddurl = "https://aip.baidubce.com/rest/2.0/face/v2/faceset/user/add?access_token=" + access_token

	resp, err := http.Get(imgurl)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	datas, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	dataface := make(url.Values)
	dataface["uid"] = []string{user.IdNumber}                              //学员身份证号   百度用户ID
	dataface["user_info"] = []string{user.Phone}                           //学员信息   百度用户信息
	dataface["group_id"] = []string{schooid}                               //驾校ID 百度人脸分组ID
	dataface["image"] = []string{base64.StdEncoding.EncodeToString(datas)} //图片经过base64编码
	dataface["action_type"] = []string{"replace"}                          //默认空   replace为替换头像
	r, err := http.PostForm(faceaddurl, dataface)
	if err != nil {
		return err
	}
	defer r.Body.Close()
	respdataface, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}
	err = json.Unmarshal(respdataface, &ret_maplog)
	if err != nil {
		return err
	}
	fmt.Println(ret_maplog["error_msg"])
	if ret_maplog["error_msg"] != nil {
		return errors.New("上传百度人脸失败！")
	}
	return nil
}
func (c *Coach) GetInstitution(data map[string]string) (code string, err error) {
	var (
		url     string
		ret_map map[string]interface{}
		//req_type int64
	)
	reqData := map[string]interface{}{
		"inscode": data["school_code"],                            //培训机构编号
		"name":    data["name"],                                   //培训机构名称
		"sex":     data["sex"],                                    //性别
		"idcard":  strings.Replace(data["idNumber"], "c", "", -1), //身份证号
		"mobile":  strings.Replace(data["phone"], "c", "", -1),    //手机号码
		//"address": user.Address,                                //联系地址
		"photo": data["portrait_code"], //照片文件ID
		//"fingerprint":   finger,                                      //指纹图片ID
		"drilicence":    c.LicenceNumber,                       //驾驶证号
		"fstdrilicdate": c.LicenceGrantDate.Format("20060102"), //驾驶证初领日期
		//"occupationno":    c.OccupationNumber,                          //职业资格证号
		"occupationlevel": c.OccupationRank, //职业资格等级
		// "dripermitted":    c.DrivingCarType, //准驾车型
		// "teachpermitted":  c.TeachingCarType,              //准教车型
		"employstatus": c.Status,                       //供职状态
		"hiredate":     c.EntryDate.Format("20060102"), //入职日期
		"address":      data["address"],
		"fingerprint":  data["finger"],
		"occupationno": c.OccupationNumber,
	}
	if data["province"] == "420000" {
		reqData["teachpermitted"] = c.TeachingCarTypes
		reqData["dripermitted"] = c.DrivingCarTypes
	} else {
		reqData["teachpermitted"] = c.TeachingCarType
		reqData["dripermitted"] = c.DrivingCarType
	}
	//请求获取加密地址
	if url, err = utils.GetSignURL("coach", reqData, 1, data["province"], data["city"]); err != nil {
		return "", err
	}
	param, err := json.Marshal(reqData)
	if err != nil {
		fmt.Println("json.Marshal failed:", err)
		return
	}
	var api_log ApiLog
	api_log.Url = url
	api_log.Param = string(param)
	api_log.Method = "POST"
	api_log.Time = time.Now()
	//请求运管
	if ret_map, err = utils.APIReq(url, reqData, "POST"); err != nil {
		result, _ := json.Marshal(ret_map)
		api_log.Result = string(result)
		api_log.Add()
		return "", err
	}
	result, _ := json.Marshal(ret_map)
	api_log.Result = string(result)
	api_log.Add()
	errorcode, _ := cast.ToStringE(ret_map["errorcode"])
	if errorcode != "0" {
		return "", errors.New(ret_map["message"].(string))
	}
	if md, ok := ret_map["data"].(map[string]interface{}); ok {

		return cast.ToString(md["coachnum"]), nil
	}
	return "", errors.New("获取教练编号失败")
}

// RecordCoach 备案教练员
func (c *Coach) RecordCoach(data map[string]string) (err error) {
	reqData := map[string]interface{}{
		"inscode":  data["school_code"],                            //培训机构编号
		"coachnum": c.InstitutionCode,                              //教练员编号
		"name":     data["name"],                                   //姓名
		"sex":      data["sex"],                                    //性别
		"idcard":   strings.Replace(data["idNumber"], "c", "", -1), //身份证号
		"mobile":   strings.Replace(data["phone"], "c", "", -1),    //手机号码
		//"address":  user.Address,                                //联系地址
		"photo": data["portrait_code"], //照片文件ID
		//"fingerprint":     finger.Institution_code,                     //指纹图片ID
		"drilicence":    c.LicenceNumber,                       //驾驶证号
		"fstdrilicdate": c.LicenceGrantDate.Format("20060102"), //驾驶证初领日期
		//"occupationno":    c.OccupationNumber,                    //职业资格证号
		"occupationlevel": c.OccupationRank, //职业资格等级
		//"dripermitted":    c.DrivingCarType, //准驾车型
		//"teachpermitted":  c.TeachingCarType,              //准教车型
		"employstatus": c.Status,                       //供职状态0:在职1:离职
		"hiredate":     c.EntryDate.Format("20060102"), //入职日期
		//"leavedate":       leavedate,                                   //离职日期
	}
	if data["province"] == "420000" {
		reqData["teachpermitted"] = c.TeachingCarTypes
		reqData["dripermitted"] = c.DrivingCarTypes
	} else {
		reqData["teachpermitted"] = c.TeachingCarType
		reqData["dripermitted"] = c.DrivingCarType
	}

	var (
		apiurl   string
		ret_map  map[string]interface{}
		req_type int64
	)
	if data["city"] == "130100" {
		req_type = 3
		if c.Subject == "1" {
			reqData["teachtype"] = "3"
		} else if c.Subject == "2" {
			reqData["teachtype"] = "6"
		} else if c.Subject == "3" {
			reqData["teachtype"] = "7"
		}
	} else {
		req_type = 2
		if c.Subject == "1" {
			reqData["teachtype"] = "0"
		} else if c.Subject == "2" {
			reqData["teachtype"] = "1"
		} else if c.Subject == "3" {
			reqData["teachtype"] = "2"
		} else if c.Subject == "4" {
			reqData["teachtype"] = "3"
		} else if c.Subject == "5" {
			reqData["teachtype"] = "4"
		}
	}
	if c.Status == "1" {
		reqData["leavedate"] = c.DepartureDate.Format("20060102")
	}
	if reqData["photo"], err = utils.Fileid(data["image_url"], "coachimg", req_type, data["province"], data["city"]); err != nil {
		return err
	}
	//data["photo"], _ = new(api.BaseController).Fileid(portrait.Image_url, "coachimg", 2)
	//请求获取加密地址
	if data["province"] != "520000" {
		reqData["address"] = data["address"]
		reqData["fingerprint"] = data["finger"]
		reqData["occupationno"] = c.OccupationNumber
	}
	if apiurl, err = utils.GetSignURL("coach", reqData, req_type, data["province"], data["city"]); err != nil {
		return err
	}
	param, err := json.Marshal(reqData)
	if err != nil {
		fmt.Println("json.Marshal failed:", err)
		return
	}
	var api_log ApiLog
	api_log.Url = apiurl
	api_log.Param = string(param)
	api_log.Method = "POST"
	api_log.Time = time.Now()
	//请求运管
	if ret_map, err = utils.APIReq(apiurl, reqData, "POST"); err != nil {
		result, _ := json.Marshal(ret_map)
		api_log.Result = string(result)
		api_log.Add()
		return err
	}
	result, _ := json.Marshal(ret_map)
	api_log.Result = string(result)
	api_log.Add()
	fmt.Println(ret_map)
	if cast.ToString(ret_map["errorcode"]) != "0" && !strings.Contains(cast.ToString(ret_map["message"]), "已经备案") {
		return errors.New(ret_map["message"].(string))
	}
	if data["province"] == "340000" {
		fmt.Println("是否到此一游")
		reqData["photoPath"] = data["image_url"]
		reqData["baTime"] = time.Now().Format("2006-01-02 15:04:05")
		delete(reqData, "photo")
		if resp, err := utils.AnHuiServiceAPIURLRequest("driverBA/add.do", "POST", data["school_code"], reqData); err != nil {
			logs.ZapLogs.Error(err.Error(), zap.String("coach", cast.ToString(resp["token"])))
			// utils.Logfile("anhuicoach", "log.anhuicoach.log")
			// utils.Logfile(err, "log.anhuicoachadd.log")
		} else {
			// fmt.Println(resp, "driverBA/add.do")
			logs.ZapLogs.Info("AnHuiServiceAPIURLRequest", zap.String("coach", cast.ToString(resp["token"])))
		}
	}
	return nil
}

func (c *Coach) Edit(who ...string) (coach *Coach, err error) {
	if _, err = engine.Table("dts_coach").Id(c.Id).Cols(who...).Update(c); err != nil {
		return nil, err
	}
	return c, err
}
